package com.biubiu.biubiuexam.services;

import cn.hutool.core.util.IdUtil;
import com.biubiu.biubiuexam.common.dto.*;
import com.biubiu.biubiuexam.common.lang.Result;
import com.biubiu.biubiuexam.nosql.model.Exam;
import com.biubiu.biubiuexam.nosql.model.ExamPaper;
import com.biubiu.biubiuexam.nosql.model.ExamQuestion;
import com.biubiu.biubiuexam.nosql.repository.ExamPaperRepository;
import com.biubiu.biubiuexam.nosql.repository.ExamQuestionRepository;
import com.biubiu.biubiuexam.nosql.repository.ExamRepository;
import com.biubiu.biubiuexam.sql.entity.Clazz;
import com.biubiu.biubiuexam.sql.entity.User;
import com.biubiu.biubiuexam.sql.repository.ClazzRepository;
import com.biubiu.biubiuexam.sql.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.DateFormat;
import java.util.*;


/**
 * The type Teacher service.
 */
@Service
public class TeacherService {

    private final UserRepository userRepository;

    private final ClazzRepository clazzRepository;

    private final ExamRepository examRepository;

    private final ExamPaperRepository examPaperRepository;

    private final ExamQuestionRepository examQuestionRepository;

    /**
     * Instantiates a new Teacher service.
     *
     * @param userRepository         the user repository
     * @param clazzRepository        the clazz repository
     * @param examRepository         the exam repository
     * @param examPaperRepository    the exam paper repository
     * @param examQuestionRepository the exam question repository
     */
    @Autowired
    public TeacherService(UserRepository userRepository,
                          ClazzRepository clazzRepository,
                          ExamRepository examRepository,
                          ExamPaperRepository examPaperRepository,
                          ExamQuestionRepository examQuestionRepository) {
        this.userRepository = userRepository;
        this.clazzRepository = clazzRepository;
        this.examRepository = examRepository;
        this.examPaperRepository = examPaperRepository;
        this.examQuestionRepository = examQuestionRepository;
    }

    private List<TeacherExamInfoDto> getClazzAllExams(Long clazzId) {
        Optional<Clazz> clazzPtr = clazzRepository.findById(clazzId);
        if (clazzPtr.isEmpty()) {
            return new ArrayList<>();
        }

        List<Exam> examList = examRepository.findAllExamByClazzId(clazzId);

        List<TeacherExamInfoDto> tempList = new ArrayList<>();

        for (Exam item : examList) {
            TeacherExamInfoDto temp = new TeacherExamInfoDto();
            temp.setClazzCode(clazzPtr.get().getCode());
            temp.setName(item.getName());
            temp.setExamPaperLinks(item.getExamPaperLinks());
            temp.setStartTime(item.getStartTime());
            temp.setEndTime(item.getEndTime());
            temp.setDescription(item.getDescription());
            temp.setLink(item.getLink());
            tempList.add(temp);
        }
        return tempList;
    }

    private List<UserInfoDto> getClazzAllStudentInfos(Clazz clazz) {
        List<UserInfoDto> students = new ArrayList<>();

        for (User student : clazz.getStudents()) {
            UserInfoDto temp = new UserInfoDto();
            temp.setNickName(student.getNickName());
            temp.setEmail(student.getEmail());
            temp.setDescription(student.getDescription());
            students.add(temp);
        }
        return students;
    }

    private boolean verifyExamPapers(List<String> examPaperLinks) {
        for (String link : examPaperLinks) {
            ExamPaper examPaper = examPaperRepository.findExamPaperByLink(link);
            if (examPaper == null) {
                return false;
            }
        }
        return true;
    }

    private boolean verifyExamQuestions(List<String> examQuestionLinks) {
        for (String link : examQuestionLinks) {
            ExamQuestion examQuestion = examQuestionRepository.findExamQuestionByLink(link);
            if (examQuestion == null) {
                return false;
            }
        }
        return true;
    }


    /**
     * Gets all clazz of teacher.
     *
     * @param teacherId the teacher id
     * @return the all clazz of teacher
     */
    public Result getAllClazzOfTeacher(Long teacherId) {

        User teacher = userRepository.getById(teacherId);

        List<Clazz> list = clazzRepository.findAllByTeacher(teacher);
        List<TeacherClazzInfoDto> reList = new ArrayList<>();

        for (Clazz clazz : list) {
            TeacherClazzInfoDto temp = new TeacherClazzInfoDto();
            temp.setName(clazz.getName());
            temp.setDescription(clazz.getDescription());
            temp.setExams(this.getClazzAllExams(clazz.getId()));
            temp.setStudents(this.getClazzAllStudentInfos(clazz));
            temp.setCode(clazz.getCode());
            reList.add(temp);
        }

        return Result.success(reList);
    }

    /**
     * Gets clazz info.
     *
     * @param code the code
     * @return the clazz info
     */
    public Result getClazzInfo(String code) {

        Clazz clazz = clazzRepository.findByCode(code);
        if (clazz == null) {
            return Result.fail(404, "没有对应班级！", null);
        }

        TeacherClazzInfoDto teacherClazzInfoDto = new TeacherClazzInfoDto();
        teacherClazzInfoDto.setExams(this.getClazzAllExams(clazz.getId()));
        teacherClazzInfoDto.setDescription(clazz.getDescription());
        teacherClazzInfoDto.setStudents(this.getClazzAllStudentInfos(clazz));
        teacherClazzInfoDto.setName(clazz.getName());
        teacherClazzInfoDto.setCode(clazz.getCode());

        return Result.success(teacherClazzInfoDto);
    }

    /**
     * Create clazz result.
     *
     * @param teacherId      the teacher id
     * @param createClazzDto the create clazz dto
     * @return the result
     */
    public Result createClazz(Long teacherId, TeacherCreateClazzDto createClazzDto) {
        User teacher = userRepository.getById(teacherId);
        String code = IdUtil.objectId();

        Date date = new Date();
        DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);
        String formattedDate = dateFormat.format(date);

        Clazz clazz = new Clazz(teacher, code, createClazzDto.getName(), formattedDate);
        clazz.setDescription(createClazzDto.getDescription());

        clazzRepository.save(clazz);

        StudentClazzDto studentClazzDto = new StudentClazzDto();
        studentClazzDto.setName(clazz.getName());
        studentClazzDto.setDescription(clazz.getDescription());
        studentClazzDto.setTeacherName(clazz.getTeacher().getNickName());
        studentClazzDto.setTeacherEmail(clazz.getTeacher().getEmail());
        studentClazzDto.setCode(clazz.getCode());

        return Result.success(studentClazzDto);
    }

    /**
     * Del clazz result.
     *
     * @param teacherId the teacher id
     * @param code      the link
     * @return the result
     */
    public Result delClazz(Long teacherId, String code) {
        Clazz clazz = clazzRepository.findByCode(code);
        if (clazz == null) {
            return Result.fail(404, "没有对应班级！", null);
        }
        if (!Objects.equals(clazz.getTeacher().getId(), teacherId)) {
            return Result.fail(401, "您不是班主任！", null);
        }
        clazzRepository.delete(clazz);
        return Result.success(null);
    }

    /**
     * Edit clazz result.
     *
     * @param teacherId the teacher id
     * @param clazzDto  the clazz dto
     * @return the result
     */
    public Result editClazz(Long teacherId, TeacherEditClazzDto clazzDto) {
        Clazz clazz = clazzRepository.findByCode(clazzDto.getCode());
        if (clazz == null) {
            return Result.fail(404, "没有对应班级！", null);
        }
        if (!Objects.equals(clazz.getTeacher().getId(), teacherId)) {
            return Result.fail(401, "您不是班主任！", null);
        }
        clazz.setName(clazzDto.getName());
        clazz.setDescription(clazzDto.getDescription());

        clazzRepository.save(clazz);

        return Result.success(clazzDto);
    }

    /**
     * Create exam result.
     *
     * @param teacherId     the teacher id
     * @param createExamDto the create exam dto
     * @return the result
     */
    public Result createExam(Long teacherId, TeacherCreateExamDto createExamDto) {

        Clazz clazz = clazzRepository.findByCode(createExamDto.getClazzCode());
        if (clazz == null) {
            return Result.fail(404, "没有对应班级！", null);
        }

        if (!Objects.equals(clazz.getTeacher().getId(), teacherId)) {
            return Result.fail(401, "您不是班主任！", null);
        }

        if (!this.verifyExamPapers(createExamDto.getExamPaperLinks())) {
            return Result.fail(404, "没有对应试卷！", null);
        }

        Exam exam = new Exam();
        exam.setId(IdUtil.objectId());
        exam.setClazzId(clazz.getId());
        exam.setName(createExamDto.getName());
        exam.setStartTime(createExamDto.getStartTime());
        exam.setEndTime(createExamDto.getEndTime());
        exam.setDescription(createExamDto.getDescription());
        exam.setExamPaperLinks(createExamDto.getExamPaperLinks());
        exam.setLink(IdUtil.objectId());

        examRepository.save(exam);

        TeacherExamDto examDto = new TeacherExamDto();
        examDto.setName(exam.getName());
        examDto.setClazzCode(clazz.getCode());
        examDto.setStartTime(exam.getStartTime());
        examDto.setEndTime(exam.getEndTime());
        examDto.setExamPaperLinks(exam.getExamPaperLinks());
        examDto.setLink(exam.getLink());
        examDto.setDescription(exam.getDescription());

        return Result.success(examDto);
    }

    /**
     * Edit exam result.
     *
     * @param teacherId          the teacher id
     * @param teacherEditExamDto the teacher edit exam dto
     * @return the result
     */
    public Result editExam(Long teacherId, TeacherEditExamDto teacherEditExamDto) {
        Exam examObj = examRepository.findExamByLink(teacherEditExamDto.getLink());
        if (examObj == null) {
            return Result.fail(404, "没有对应考试！", null);
        }
        Optional<Clazz> clazzPtr = clazzRepository.findById(examObj.getClazzId());
        if (clazzPtr.isEmpty()) {
            return Result.fail(400, "未知错误！", null);
        }

        if (!Objects.equals(clazzPtr.get().getTeacher().getId(), teacherId)) {
            return Result.fail(401, "您不是班主任！", null);
        }

        if (!this.verifyExamPapers(teacherEditExamDto.getExamPaperLinks())) {
            return Result.fail(404, "没有对应试卷！", null);
        }


        examObj.setName(teacherEditExamDto.getName());
        examObj.setStartTime(teacherEditExamDto.getStartTime());
        examObj.setEndTime(teacherEditExamDto.getEndTime());
        examObj.setExamPaperLinks(teacherEditExamDto.getExamPaperLinks());
        examObj.setDescription(teacherEditExamDto.getDescription());
        examRepository.save(examObj);

        return Result.success(teacherEditExamDto);
    }

    /**
     * Del exam result.
     *
     * @param teacherId the teacher id
     * @param link      the link
     * @return the result
     */
    public Result delExam(Long teacherId, String link) {
        Exam examObj = examRepository.findExamByLink(link);
        if (examObj == null) {
            return Result.fail(404, "没有对应考试！", null);
        }
        Optional<Clazz> clazzPtr = clazzRepository.findById(examObj.getClazzId());
        if (clazzPtr.isPresent()) {
            if (!Objects.equals(clazzPtr.get().getTeacher().getId(), teacherId)) {
                return Result.fail(401, "您不是班主任！", null);
            }
        }

        examRepository.delete(examObj);
        return Result.success(null);
    }

    /**
     * Create exam paper result.
     *
     * @param teacherId                 the teacher id
     * @param teacherCreateExamPaperDto the teacher create exam paper dto
     * @return the result
     */
    public Result createExamPaper(Long teacherId, TeacherCreateExamPaperDto teacherCreateExamPaperDto) {
        String link = IdUtil.objectId();
        User teacher = userRepository.getById(teacherId);
        ExamPaper examPaper = new ExamPaper(link, teacherCreateExamPaperDto.getTitle(), teacherId, teacherCreateExamPaperDto.getDescription(), teacherCreateExamPaperDto.getExamQuestionLinks(), link);
        examPaperRepository.save(examPaper);

        if (!this.verifyExamQuestions(teacherCreateExamPaperDto.getExamQuestionLinks())) {
            return Result.fail(404, "没有对应题目！", null);
        }

        TeacherExamPaperDto teacherExamDto = new TeacherExamPaperDto(examPaper.getTitle(),
                teacher.getNickName(),
                examPaper.getExamQuestionLinks(),
                examPaper.getLink(),
                examPaper.getDescription());

        return Result.success(teacherExamDto);
    }

    /**
     * Gets my all exam paper.
     *
     * @param teacherId the teacher id
     * @return the my all exam paper
     */
    public Result getMyAllExamPaper(Long teacherId) {

        User teacher = userRepository.getById(teacherId);

        List<ExamPaper> list = examPaperRepository.findExamPaperAllByAuthorId(teacherId);

        List<TeacherExamPaperDto> reList = new ArrayList<>();

        for (ExamPaper examPaper : list) {

            TeacherExamPaperDto temp = new TeacherExamPaperDto();
            temp.setTitle(examPaper.getTitle());
            temp.setAuthor(teacher.getNickName());
            temp.setExamQuestionLinks(examPaper.getExamQuestionLinks());
            temp.setLink(examPaper.getLink());
            temp.setDescription(examPaper.getDescription());

            reList.add(temp);
        }

        return Result.success(reList);
    }

    /**
     * Edit exam paper result.
     *
     * @param teacherId               the teacher id
     * @param teacherEditExamPaperDto the teacher edit exam paper dto
     * @return the result
     */
    public Result editExamPaper(Long teacherId, TeacherEditExamPaperDto teacherEditExamPaperDto) {
        ExamPaper examPaper = examPaperRepository.findExamPaperByLink(teacherEditExamPaperDto.getLink());
        if (examPaper == null) {
            return Result.fail(404, "没有对应试卷！", null);
        }

        if (!Objects.equals(examPaper.getAuthorId(), teacherId)) {
            return Result.fail(403, "你不是试卷的作者！", null);
        }

        if (!this.verifyExamQuestions(teacherEditExamPaperDto.getExamQuestionLinks())) {
            return Result.fail(404, "没有对应题目！", null);
        }

        examPaper.setTitle(teacherEditExamPaperDto.getTitle());
        examPaper.setDescription(teacherEditExamPaperDto.getDescription());
        examPaper.setExamQuestionLinks(teacherEditExamPaperDto.getExamQuestionLinks());
        examPaperRepository.save(examPaper);

        return Result.success(teacherEditExamPaperDto);
    }

    /**
     * Del exam paper result.
     *
     * @param teacherId the teacher id
     * @param link      the link
     * @return the result
     */
    public Result delExamPaper(Long teacherId, String link) {
        ExamPaper examPaper = examPaperRepository.findExamPaperByLink(link);
        if (examPaper == null) {
            return Result.fail(404, "没有对应试卷！", null);
        }
        if (!Objects.equals(examPaper.getAuthorId(), teacherId)) {
            return Result.fail(403, "你不是试卷的作者！", null);
        }

        examPaperRepository.delete(examPaper);
        return Result.success(null);
    }

}
